import { Context } from 'koa';
import { getManager } from 'typeorm';
  
import { Order } from '../entity/order';
import { Client } from '../entity/client';
import { Delivery } from '../entity/delivery';
import { Statistics } from '../entity/statistics';

import DeliveryException from '../exceptions/delivery';

export default class DeliveryController {

  /**
   * 返回所有的Delivery
   * @param ctx 
   */
  public static async listDelivery(ctx: Context) {
    const deliveryRepository = getManager().getRepository(Delivery);
    const deliveries = await deliveryRepository.query(`SELECT * FROM \`delivery\` ORDER BY id DESC`);
    
    if (deliveries) {
      ctx.status = 200;
      ctx.body = deliveries;
    } else {
      ctx.status = 500;
    }
  }

  /**
   * 根据送货单ID，查找送货单，Get方法
   * @param ctx 上下文
   */
  public static async checkDelivery(ctx: Context) {
    const deliveryRepository = getManager().getRepository(Delivery);
    
    // 要查找的对象
    const id: string = ctx.params.id;
  
    const delivery = await deliveryRepository.createQueryBuilder("delivery")
      .where("delivery.id = :id", {id})
      .leftJoinAndSelect("delivery.orders", "order")
      .leftJoinAndSelect("delivery.client", "client")
      .getOne();
    
    if (delivery) {
      ctx.status = 200;
      ctx.body = delivery;
    } else {
      ctx.status = 500;
    }
  }

  /**
   * 为clientId指定的客户，添加Delivery
   * @param ctx
   */
  public static async appendDelivery(ctx: Context) {
    const deliveryRepository = getManager().getRepository(Delivery);
    const clientRepository = getManager().getRepository(Client);
    const orderRepository = getManager().getRepository(Order);
    const clientId = ctx.params.clientId;
    // 先找到对应的Client
    const client = await clientRepository.findOne(clientId);

    if (client == undefined) {
      ctx.status = 503;
      ctx.body = 'client not found';
      return;
    }

    // 表单信息
    const delivery: Delivery = ctx.request.body.delivery;
    // 该送货单里的订单id列表
    const orderIds = ctx.request.body.orderIds;

    // 找到所有这份送货单里的订单
    const ordersToDelivery = await orderRepository.createQueryBuilder("order")
      .whereInIds(orderIds)
      .getMany();

    // 统计的数据
    const statisticsRepository = getManager().getRepository(Statistics);
    let deliveryAmount = (await statisticsRepository.query(`SELECT deliveryAmount FROM statistics LIMIT 1`))[0].deliveryAmount;

    // 根据表单信息创建送货单
    const newDelivery = new Delivery();
    newDelivery.orderQuantity = delivery.orderQuantity;
    newDelivery.totalAmount = delivery.totalAmount;
    newDelivery.deliveryDate = delivery.deliveryDate;
    newDelivery.currency = delivery.currency;
    newDelivery.reviewer = delivery.reviewer;
    newDelivery.plateNumber = delivery.plateNumber;
    newDelivery.deliveryAddress = delivery.deliveryAddress;
    newDelivery.clientPhone = delivery.clientPhone;
    newDelivery.client = client;

    // 如果用户没有输入送货单号，则自动生成一个
    if (delivery.deliveryNumber == "") {
      newDelivery.deliveryNumber = delivery.deliveryDate.toString().substr(2) + (10000 + deliveryAmount).toString().substr(1);
    }
    else {
      newDelivery.deliveryNumber = delivery.deliveryNumber;
    }

    deliveryAmount += 1;

    // 将送货单里的所有订单存储起来
    newDelivery.orders = ordersToDelivery;

    // 存储这份送货单
    const deliverySaved = await deliveryRepository.save(newDelivery);
    
    if (deliverySaved) {
      await statisticsRepository.update(1, {deliveryAmount});
      ctx.status = 201;
      ctx.body = deliverySaved;
    } else {
      ctx.status = 500;
    }

  }

  /**
   * 更新送货单，表单内容。
   * @param ctx 上下文
  */
  public static async updateDelivery(ctx: Context) {
    const deliveryRepository = getManager().getRepository(Delivery);
    
    // 要修改的送货单id
    const id: string = ctx.params.id;

    const deliveryToUpdate = ctx.request.body;

    // 不允许修改送货单的订单、订单总数和订单总金额等信息
    if ('orders' in deliveryToUpdate) {
      delete deliveryToUpdate.orders;
    }
    if ('orderQuantity' in deliveryToUpdate) {
      delete deliveryToUpdate.orderQuantity;
    }
    if ('totalAmount' in deliveryToUpdate) {
      delete deliveryToUpdate.totalAmount;
    }

    // 更新
    await deliveryRepository.update(id, deliveryToUpdate);
    // 获得更新之后的对象
    const updatedDelivery = await deliveryRepository.findOne(id);
    
    if (updatedDelivery) {
      ctx.status = 200;
      ctx.body = updatedDelivery;
    } else {
      ctx.status = 500;
    }
  }

  /**
   * 移除送货单的一张订单
   * @param ctx 上下文
   */
  public static async removeOrder(ctx: Context) {
    const deliveryRepository = getManager().getRepository(Delivery);

    // 要删除的送货单
    const id = ctx.params.id;
    const delivery = await deliveryRepository.createQueryBuilder("delivery")
      .where("delivery.id = :id", {id})
      .leftJoinAndSelect("delivery.orders", "order")
      .getOne();
    
    if (delivery) {
      const orders = delivery.orders;
      const orderId = ctx.request.body?.orderId;
      const orderIndex = orders.findIndex(item => item.id === orderId);
      // 移除对应 Id 的 Order
      if (orderIndex == -1) {
        ctx.status = 500;
        ctx.body = {
          err: 'can not find order in the delivery'
        }
        return;
      }
      orders.splice(orderIndex, 1);
      // 重新计算orderQuantity和totalAmount
      delivery.orderQuantity = orders.length;
      delivery.totalAmount = orders.reduce((acc, cur) => {
        return acc + cur.amount;
      }, 0);
      await deliveryRepository.save(delivery);
    }
    else {
      ctx.status = 500;
      ctx.body = {
        message: 'can not find the delivery'
      }
      return;
    }

    ctx.status = 204;
    ctx.body = `Order removed ${id}`;
  }

  /**
   * 添加送货单的订单
   * @param ctx 上下文
   */
  public static async AddOrder(ctx: Context) {
    const deliveryRepository = getManager().getRepository(Delivery);

    // 要添加的送货单
    const id = ctx.params.id;
    const delivery = await deliveryRepository.createQueryBuilder("delivery")
      .where("delivery.id = :id", {id})
      .leftJoinAndSelect("delivery.orders", "order")
      .getOne();
    
    if (delivery) {
      const orders = delivery.orders;
      const appendOrderIds = ctx.request.body;
      console.log(appendOrderIds);
      // 判断送货单订单数量是否超额。
      if (appendOrderIds.length + orders.length > 10) {
        ctx.status = 500;
        ctx.body = {
          message: '一张送货单最多只能容纳10张订单'
        }
        return;
      }

      const orderRepository = getManager().getRepository(Order);

      // 找到所有这份送货单里的订单
      const ordersToDelivery = await orderRepository.createQueryBuilder("order")
        .whereInIds(appendOrderIds)
        .getMany();
      
      const allOrdersToDelivery = [...orders, ...ordersToDelivery];
      delivery.orders = allOrdersToDelivery;


      // 重新计算orderQuantity和totalAmount
      delivery.orderQuantity = allOrdersToDelivery.length;
      delivery.totalAmount = allOrdersToDelivery.reduce((acc, cur) => {
        return acc + cur.amount;
      }, 0);
      await deliveryRepository.save(delivery);
    }
    else {
      ctx.status = 500;
      ctx.body = {
        message: 'can not find the delivery'
      }
      return;
    }

    ctx.status = 201;
    ctx.body = delivery;
  }

  /**
   * 删除送货单，根据送货单的id，如果该送货单已经审核，则会报错。
   * @param ctx 上下文
   */
  public static async deleteDelivery(ctx: Context) {
    const deliveryRepository = getManager().getRepository(Delivery);

    // 要删除的送货单
    const id = ctx.params.id;
    const delivery = await deliveryRepository.createQueryBuilder("delivery")
      .where("delivery.id = :id", {id})
      .leftJoinAndSelect("delivery.orders", "order")
      .getOne();

    // 如果找不到这个order
    if (delivery == undefined) {
      ctx.status = 404;
      ctx.body = {
        message: 'Delivery not found'
      };
      return;
    }
    // 如果该订单已经被delivery选定
    if (delivery.reviewed == true) {
      ctx.status = 409;
      ctx.body = {
        message: '该送货单已审核，不允许删除，如要删除，请点击复审。'
      };
      return;
    }

    // 删除对应送货单的对应订单
    delivery.orders = [];
    await deliveryRepository.save(delivery);

    // 删除对应送货单
    await deliveryRepository.delete(id);
  
    ctx.status = 204;
    ctx.body = `Delivery deleted ${id}`;
  }

  /**
   * 审核订单，根据送货单的id，如果该送货单已经审核，则会报错。
   * @param ctx 上下文
   */
  public static async reviewDelivery(ctx: Context) {
    const deliveryRepository = getManager().getRepository(Delivery);

    // 要审核的送货单
    const id = ctx.params.id;
    const delivery = await deliveryRepository.createQueryBuilder("delivery")
      .where("delivery.id = :id", {id})
      .getOne();

    // 如果找不到这个送货单
    if (delivery == undefined) {
      ctx.status = 403;
      ctx.body = {
        message: 'Delivery not found'
      };
      return;
    }
    // 如果该订单已经被审核
    if (delivery.reviewed == true) {
      ctx.status = 409;
      ctx.body = {
        message: 'Delivery has been reviewed'
      };
      return;
    }

    // 审核对应送货单的对应订单
    delivery.reviewed = true;
    await deliveryRepository.save(delivery);
  
    ctx.status = 204;
  }


  /**
   * 取消审核送货单，根据送货单的id，如果该送货单已经审核，则会报错。
   * @param ctx 上下文
   */
  public static async unreviewDelivery(ctx: Context) {
    const deliveryRepository = getManager().getRepository(Delivery);

    // 要审核的送货单
    const id = ctx.params.id;
    const delivery = await deliveryRepository.createQueryBuilder("delivery")
      .where("delivery.id = :id", {id})
      .getOne();

    // 如果找不到这个送货单
    if (delivery == undefined) {
      ctx.status = 403;
      ctx.body = {
        message: 'Delivery not found'
      };
      return;
    }
    // 如果该订单未被审核
    if (delivery.reviewed == false) {
      ctx.status = 409;
      ctx.body = {
        message: 'Delivery has not been reviewed'
      };
      return;
    }

    // 审核对应送货单的对应订单
    delivery.reviewed = false;
    await deliveryRepository.save(delivery);
  
    ctx.status = 204;
  }

  /**
   * 送货单付款，要求该送货单已审核。
   * @param ctx 上下文
   */
  public static async payDelivery(ctx: Context) {
    const deliveryRepository = getManager().getRepository(Delivery);

    // 要审核的送货单
    const id = ctx.params.id;
    const delivery = await deliveryRepository.createQueryBuilder("delivery")
      .where("delivery.id = :id", {id})
      .getOne();

    // 如果找不到这个送货单
    if (delivery == undefined) {
      throw new DeliveryException.NotFoundException();
    }
    // 如果该订单尚未审核
    if (delivery.reviewed == false) {
      throw new DeliveryException.UnReviewedException();
    }

    // 审核对应送货单的对应订单
    delivery.paid = true;
    await deliveryRepository.save(delivery);
  
    ctx.status = 204;
  }

  /**
   * 送货单取消付款，要求该送货单已经审核。
   * @param ctx 上下文
   */
  public static async unPayDelivery(ctx: Context) {
    const deliveryRepository = getManager().getRepository(Delivery);

    // 要审核的送货单
    const id = ctx.params.id;
    const delivery = await deliveryRepository.createQueryBuilder("delivery")
      .where("delivery.id = :id", {id})
      .getOne();

    // 如果找不到这个送货单
    if (delivery == undefined) {
      throw new DeliveryException.NotFoundException();
    }


    // 审核对应送货单的对应订单
    delivery.paid = false;
    await deliveryRepository.save(delivery);
  
    ctx.status = 204;
  }
}